package com.mycat.redis.util;

import com.mycat.redis.pool.JedisConnection;
import com.mycat.redis.pool.single.RedisSinglePool;
import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;

import java.util.List;

/**
 * Redis列表相关操作（可以重复）
 *
 * @author roger.
 * @email 190642964@qq.com
 * @create 2016-12-26
 */
public class RedisListUtil {

    private static JedisConnection getInstance() {
        return RedisSinglePool.getInstance();
    }

    /**
     * 获取列表的长度
     *
     * @param key 键
     * @return 列表为空-0，不是列表返回一个错误，否则是返回列表长度
     */
    public static long llen(String key) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.llen(key);
        jedis.close();
        return data;
    }

    /**
     * 获取列表的长度
     *
     * @param key 键
     * @return 列表为空-0，不是列表返回一个错误，否则是返回列表长度
     */
    public static long llen(byte[] key) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.llen(key);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表头中插入一个或多个值，为空先创建一个键在插入数据
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long lpush(String key, String... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.lpush(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表头中插入一个或多个值，为空先创建一个键在插入数据
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long lpush(byte[] key, byte[]... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.lpush(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表头中插入一个或多个值，当key不存在是，什么动作都不做
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long lpushx(String key, String... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.lpushx(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表头中插入一个或多个值，当key不存在是，什么动作都不做
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long lpushx(byte[] key, byte[]... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.lpushx(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表尾中插入一个或多个值，为空先创建一个键在插入数据
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long rpush(String key, String... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.rpush(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表尾中插入一个或多个值，为空先创建一个键在插入数据
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long rpush(byte[] key, byte[]... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.rpush(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表尾中插入一个或多个值，当key不存在是，什么动作都不做
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long rpushx(String key, String... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.rpushx(key, values);
        jedis.close();
        return data;
    }

    /**
     * 向一个列表尾中插入一个或多个值，当key不存在是，什么动作都不做
     *
     * @param key    键
     * @param values 一个或多个值
     * @return 列表的长度
     */
    public static long rpushx(byte[] key, byte[]... values) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.rpushx(key, values);
        jedis.close();
        return data;
    }

    /**
     * 在pivot这个元素之前插入value
     *
     * @param key   键
     * @param pivot 相对元素值
     * @param value 插入的元素值
     * @return 命令执行成功，返回命令执行成功后的列表长度。如果没有找到pivot返回[-1],如果key不存在或为空列表返回[0]
     */
    public static long linsertBefore(String key, String pivot, String value) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.linsert(key, BinaryClient.LIST_POSITION.BEFORE, pivot, value);
        jedis.close();
        return data;
    }

    /**
     * 在pivot这个元素之前插入value
     *
     * @param key   键
     * @param pivot 相对元素值
     * @param value 插入的元素值
     * @return 命令执行成功，返回命令执行成功后的列表长度。如果没有找到pivot返回[-1],如果key不存在或为空列表返回[0]
     */
    public static long linsertBefore(byte[] key, byte[] pivot, byte[] value) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.linsert(key, BinaryClient.LIST_POSITION.BEFORE, pivot, value);
        jedis.close();
        return data;
    }

    /**
     * 在pivot这个元素之后插入value
     *
     * @param key   键
     * @param pivot 相对元素值
     * @param value 插入的元素值
     * @return 命令执行成功，返回命令执行成功后的列表长度。如果没有找到pivot返回[-1],如果key不存在或为空列表返回[0]
     */
    public static long linsertAfter(String key, String pivot, String value) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.linsert(key, BinaryClient.LIST_POSITION.AFTER, pivot, value);
        jedis.close();
        return data;
    }

    /**
     * 在pivot这个元素之后插入value
     *
     * @param key   键
     * @param pivot 相对元素值
     * @param value 插入的元素值
     * @return 命令执行成功，返回命令执行成功后的列表长度。如果没有找到pivot返回[-1],如果key不存在或为空列表返回[0]
     */
    public static long linsertAfter(byte[] key, byte[] pivot, byte[] value) {
        Jedis jedis = getInstance().getResource();
        long data = jedis.linsert(key, BinaryClient.LIST_POSITION.AFTER, pivot, value);
        jedis.close();
        return data;
    }

    /**
     * 返回列表key中指定的区间的元素，当key不存在是返回一个空的列表。区间以偏移量start，stop指定。
     * start、stop以0开始，0表示第一个元素，1表示第二个元素，以此类推。
     * -1表示最后一个元素，-2表示倒数第二个元素，以此类推。
     *
     * @param key   键
     * @param start 开始偏移量，
     * @param stop  结束偏移量
     * @return 列表key某区间的元素
     */
    public static List<String> lrange(String key, long start, long stop) {
        Jedis jedis = getInstance().getResource();
        List<String> data = jedis.lrange(key, start, stop);
        jedis.close();
        return data;
    }

    /**
     * 返回列表key中指定的区间的元素，当key不存在是返回一个空的列表。区间以偏移量start，stop指定。
     * start、stop以0开始，0表示第一个元素，1表示第二个元素，以此类推。
     * -1表示最后一个元素，-2表示倒数第二个元素，以此类推。
     *
     * @param key   键
     * @param start 开始偏移量，
     * @param stop  结束偏移量
     * @return 列表key某区间的元素
     */
    public static List<byte[]> lrange(byte[] key, long start, long stop) {
        Jedis jedis = getInstance().getResource();
        List<byte[]> data = jedis.lrange(key, start, stop);
        jedis.close();
        return data;
    }

    /**
     * 从列表中获取下标为index的元素
     *
     * @param key   键
     * @param index 元素位置
     * @return 获取的元素，不存在返回null
     */
    public static String lindex(String key, long index) {
        Jedis jedis = getInstance().getResource();
        String data = jedis.lindex(key, index);
        jedis.close();
        return data;
    }

    /**
     * 从列表中获取下标为index的元素
     *
     * @param key   键
     * @param index 元素位置
     * @return 获取的元素，不存在返回null
     */
    public static byte[] lindex(byte[] key, long index) {
        Jedis jedis = getInstance().getResource();
        byte[] data = jedis.lindex(key, index);
        jedis.close();
        return data;
    }
}
